package com.aoip.telemetry.telemetry.configureui.business.analysis.group.service.impl;

import com.aoip.telemetry.telemetry.configureui.business.analysis.element.mapper.ElementConfigMapper;
import com.aoip.telemetry.telemetry.configureui.business.analysis.group.mapper.ElementAnalysisGroupConfigMapper;
import com.aoip.telemetry.telemetry.configureui.business.analysis.group.mapper.RelElementAnalysisGroupConfigMapper;
import com.aoip.telemetry.telemetry.configureui.business.analysis.group.service.ElementAnalysisGroupService;
import com.aoip.telemetry.telemetry.configureui.business.util.CommonMethod;
import com.aoip.telemetry.telemetry.core.redis.RedisCache;
import com.aoip.telemetry.telemetry.entity.element.ElementAnalysisGroupConfigEntity;
import com.aoip.telemetry.telemetry.entity.element.ElementConfigEntity;
import com.aoip.telemetry.telemetry.entity.element.RelElementAnalysisGroupConfigEntity;
import com.aoip.telemetry.telemetry.entity.enums.CacheKeyEnum;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author chenbai
 * @version 1.0
 * @date 2021/12/29 15:28
 */
@Service
@DS("telemetry")
public class ElementAnalysisGroupServiceImpl implements ElementAnalysisGroupService {
    @Resource
    private ElementAnalysisGroupConfigMapper mapper;
    @Resource
    private RelElementAnalysisGroupConfigMapper relElementGroupMapper;

    @Resource
    private ElementConfigMapper elementMapper;

    @Resource
    private RedisCache redisCache;

    @Override
    public List<ElementAnalysisGroupConfigEntity> list(ElementAnalysisGroupConfigEntity entity) {
        QueryWrapper<ElementAnalysisGroupConfigEntity> queryWrapper = new QueryWrapper<>();
        String analysisGroupName = entity.getAnalysisGroupName();
        if (StringUtils.hasText(analysisGroupName)) {
            queryWrapper.like("analysis_group_name", analysisGroupName);
        }
        return mapper.selectList(queryWrapper);
    }

    @Override
    public List<ElementConfigEntity> elementAnalysisList(String analysisGroupId) {
        return sortedElement(analysisGroupId);
    }

    private List<ElementConfigEntity> sortedElement(String analysisGroupId) {
        QueryWrapper<RelElementAnalysisGroupConfigEntity> groupQueryWrapper = new QueryWrapper<>();
        groupQueryWrapper.eq("analysis_group_id", analysisGroupId);
        groupQueryWrapper.orderBy(true, true, "analysis_order");
        List<RelElementAnalysisGroupConfigEntity> analysisGroupConfigEntityList = relElementGroupMapper.selectList(groupQueryWrapper);

        QueryWrapper<ElementConfigEntity> queryWrapper = new QueryWrapper<>();
        List<String> ids = analysisGroupConfigEntityList
                .stream()
                .map(RelElementAnalysisGroupConfigEntity::getAnalysisId)
                .collect(Collectors.toList());
        if (ids.size() < 1) {
            return new ArrayList<>();
        }
        queryWrapper.in("id", ids);
        List<ElementConfigEntity> tempElementList = elementMapper.selectList(queryWrapper);
        List<ElementConfigEntity> elementList = new ArrayList<>(tempElementList.size());
        for (String id : ids) {
            for (ElementConfigEntity entity : tempElementList) {
                if (id.equals(entity.getId())) {
                    elementList.add(entity);
                    break;
                }
            }
        }
        return elementList;
    }

    @Override
    public int add(List<String> analysisIds, ElementAnalysisGroupConfigEntity analysisGroupEntity) {
        String analysisGroupId = analysisGroupEntity.getId();
        if (StringUtils.hasText(analysisGroupId)) {
            mapper.updateById(analysisGroupEntity);
        } else {
            mapper.insert(analysisGroupEntity);
        }
        for (int i = 0; i < analysisIds.size(); i++) {
            RelElementAnalysisGroupConfigEntity entity = new RelElementAnalysisGroupConfigEntity();
            // 不可直接用id，因为采用mybatis-plus 执行insert 后主键id才存入实体类中，之前声明的字符串id为空
            entity.setAnalysisGroupId(analysisGroupEntity.getId());
            entity.setAnalysisId(analysisIds.get(i));
            entity.setAnalysisOrder(i);
            relElementGroupMapper.insert(entity);
        }
        redisCache.setCacheList(CacheKeyEnum.ANALYSIS_GROUP + ":" + analysisGroupEntity.getId() + analysisGroupEntity.getFuncCode(), analysisIds);
        return analysisIds.size() + 1;
    }

    @Override
    public int edit(List<String> analysisIds, ElementAnalysisGroupConfigEntity analysisGroupEntity) {
        String analysisGroupId = analysisGroupEntity.getId();
        QueryWrapper<RelElementAnalysisGroupConfigEntity> groupQueryWrapper = new QueryWrapper<>();
        groupQueryWrapper.eq("analysis_group_id", analysisGroupId);
        groupQueryWrapper.orderBy(true, true, "analysis_order");
        List<RelElementAnalysisGroupConfigEntity> list = relElementGroupMapper.selectList(groupQueryWrapper);
        if (list == null || list.size() < 1) {
            return add(analysisIds, analysisGroupEntity);
        }
        List<RelElementAnalysisGroupConfigEntity> updateList = new ArrayList<>();
        List<RelElementAnalysisGroupConfigEntity> insertList = new ArrayList<>();
        List<String> ignoreIds = new ArrayList<>();
        List<String> existIds = new ArrayList<>();
        int listSize = list.size();
        for (int i = 0; i < analysisIds.size(); i++) {
            String analysisId = analysisIds.get(i);
            if (listSize <= i) {
                RelElementAnalysisGroupConfigEntity groupItem = new RelElementAnalysisGroupConfigEntity();
                groupItem.setAnalysisOrder(i);
                groupItem.setAnalysisGroupId(analysisGroupId);
                groupItem.setAnalysisId(analysisId);
                insertList.add(groupItem);
                continue;
            }
            RelElementAnalysisGroupConfigEntity item = list.get(i);
            if (analysisId.equals(item.getAnalysisId())) {
                ignoreIds.add(item.getId());
                continue;
            }
            boolean exist = true;
            for (RelElementAnalysisGroupConfigEntity entity : list) {
                if (entity.getAnalysisId().equals(analysisId)) {
                    String id = entity.getId();
                    RelElementAnalysisGroupConfigEntity groupItem = new RelElementAnalysisGroupConfigEntity();
                    groupItem.setAnalysisOrder(i);
                    groupItem.setAnalysisId(analysisId);
                    groupItem.setAnalysisGroupId(analysisGroupId);
                    groupItem.setId(id);
                    updateList.add(groupItem);
                    existIds.add(id);
                    exist = false;
                    break;
                }
            }
            if (exist) {
                RelElementAnalysisGroupConfigEntity groupItem = new RelElementAnalysisGroupConfigEntity();
                groupItem.setAnalysisOrder(i);
                groupItem.setAnalysisId(analysisId);
                groupItem.setAnalysisGroupId(analysisGroupId);
                insertList.add(groupItem);
            }
        }
        // 需要删除的元素 = 原来所有的元素 - 不做任何处理的元素 - 之前已存在但是仅改变元素在组中顺序的元素
        List<String> deleteIds = list.stream()
                .map(RelElementAnalysisGroupConfigEntity::getId)
                .filter(item -> !ignoreIds.contains(item))
                .filter(item -> !existIds.contains(item))
                .collect(Collectors.toList());
        if (insertList.size() > 0) {
            insertList.forEach(item -> relElementGroupMapper.insert(item));
        }
        if (updateList.size() > 0) {
            updateList.forEach(item -> relElementGroupMapper.updateById(item));
        }
        if (deleteIds.size() > 0) {
            deleteIds.forEach(item -> relElementGroupMapper.deleteById(item));
        }
        redisCache.deleteObject(CacheKeyEnum.ANALYSIS_GROUP + ":" + analysisGroupId + analysisGroupEntity.getFuncCode());
        redisCache.setCacheList(CacheKeyEnum.ANALYSIS_GROUP + ":" + analysisGroupId + analysisGroupEntity.getFuncCode(), analysisIds);
        mapper.updateById(analysisGroupEntity);
        return insertList.size() + updateList.size() + deleteIds.size();
    }

    /**
     * 数据格式（解析组编码，解析组下各个要素id集合）
     **/
    @Override
    public int initCache() {
        List<ElementAnalysisGroupConfigEntity> groupList = list(new ElementAnalysisGroupConfigEntity());
        QueryWrapper<RelElementAnalysisGroupConfigEntity> groupQueryWrapper = new QueryWrapper<>();
        List<RelElementAnalysisGroupConfigEntity> list = relElementGroupMapper.selectList(groupQueryWrapper);
        Map<String, List<String>> map = new HashMap<>();
        list.forEach(item -> {
            String analysisGroupId = item.getAnalysisGroupId();
            String funcCode = "";
            for (ElementAnalysisGroupConfigEntity group : groupList) {
                if (group.getId().equals(analysisGroupId)) {
                    funcCode = group.getFuncCode();
                    if (!StringUtils.hasText(funcCode)) {
                        funcCode = "";
                    }
                }
            }
            String analysisId = item.getAnalysisId();
            CommonMethod.collectIdToMap(analysisGroupId + funcCode, analysisId, map);
        });
        Collection<String> keys = redisCache.keys(CacheKeyEnum.ANALYSIS_GROUP + ":*");
        redisCache.deleteObject(keys);
        map.forEach((key, val) -> redisCache.setCacheList(CacheKeyEnum.ANALYSIS_GROUP + ":" + key, val));
        return list.size();
    }

    @Override
    public void delete(String[] analysisGroupIds) {
        for (String id : analysisGroupIds) {
            QueryWrapper<RelElementAnalysisGroupConfigEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("analysis_group_id", id);
            relElementGroupMapper.delete(queryWrapper);
            redisCache.deleteObject(CacheKeyEnum.ANALYSIS_GROUP + ":" + id);
            mapper.deleteById(id);
        }
    }
}
